/****************** 头文件导入 宏定义 **********************/
#include "ArduinoJson-v5.13.2.h"
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

#define MSG_BUFFER_SIZE (200)

/***************** 常量 配置区 ************************/
const char *ssid = "0_SevDaisy Mate 10";
const char *password = "66752928";

const char *mqtt_server = "47.93.197.229";
const char *user_name = "esp8266_IoT";
const char *user_passwd = "123456";
const char *topic_rgb = "ZUCC-ZYY/rgb";
const char *topic_dht = "ZUCC-ZYY/esp";

/***************** 全局变量 配置区 ************************/
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
char msg[MSG_BUFFER_SIZE];
const size_t capacity_dump_dht = JSON_OBJECT_SIZE(2);
DynamicJsonBuffer jsonBuffer_dump_dht(capacity_dump_dht);
const size_t capacity_load_rgb = JSON_OBJECT_SIZE(3) + 20;
DynamicJsonBuffer jsonBuffer_load_rgb(capacity_load_rgb);

/***************** 函数声明 ************************/
void setup_wifi();
void mqtt_callback(char *topic, byte *payload, unsigned int length);
void reconnect();
void pub_dht(float temperature, float humidity);
void prase_rgb(byte *payload, int *out);

void setup_wifi()
{
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void mqtt_callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  String str = "";
  for (int i = 0; i < length; i++)
  {
    str += (char)payload[i];
  }
  Serial.println(str);
}

void reconnect()
{
  while (!client.connected())
  {
    Serial.print("Attempting MQTT connection...");
    /* 设置 clientID 为 随机值，以保证一定范围内的重复连接，clientID不重复。否则，会出现收不到消息的情况（应该是因为服务端是按 clientID 来推送信息的） */
    String clientId = "clientID_31801146_";
    clientId += String(random(0xffff), HEX);
    if (client.connect(clientId.c_str(), user_name, user_passwd))
    {
      Serial.println("connected");
      client.subscribe(topic_rgb, 1);
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}
void pub_dht(float temperature, float humidity)
{
  JsonObject &root = jsonBuffer_dump_dht.createObject();
  root["temperature"] = temperature;
  root["humidity"] = humidity;
  char payload[50];
  root.printTo(payload, 50);
  Serial.println(payload);
  client.publish(topic_dht, payload, true);
}
void prase_rgb(byte *payload, int *out)
{
  JsonObject &root = jsonBuffer_load_rgb.parseObject(payload);
  out[0] = root["R"]; // 20
  out[1] = root["G"]; // 50
  out[2] = root["B"]; // 10
}